/**
 * @file Explicit_LMM.h
 * @brief The class for Explicit_LMM.
 * @author XDDDD
 * @version 
 * @date 2021-04-28
 */

#ifndef __PAISLEYPARK__EXPLICIT_LMM_H__
#define __PAISLEYPARK__EXPLICIT_LMM_H__

#include "LMM.h"

template <std::size_t DIM>
class Explicit_LMM : public LMM<DIM> {
public:
	/**
	 * @brief Constructor.
	 */
	Explicit_LMM(){};
	/**
	 * @brief Destructor.
	 */
	~Explicit_LMM(){};
	/**
	 * @brief Implement the one step method by explicit lmm.
	 *
	 * @param _Pnts The vector of initial points.
	 * @param _stepl The length of the step.
	 * @param _f The given vector functions.
	 */
	void one_step_method(std::vector<Point<DIM> >& _Pnts, const double _stepl, VectorFunction<DIM, DIM>& _f) const override;
};

template <std::size_t DIM>
void Explicit_LMM<DIM>::one_step_method(std::vector<Point<DIM> >& _Pnts, const double _stepl, VectorFunction<DIM, DIM>& _f) const {
	std::size_t s = this -> get_s();
	std::size_t order = this -> get_p();
	std::size_t num_init = this -> get_num_init();
	if(s == 0) {
			std::cerr << "Unset the coefficients." << std::endl;
			std::exit(-1);
	}
	if(_Pnts.size() == 1 && _Pnts[0].get_time() == 0 && num_init > 1) {
		this -> starting_method(_Pnts, _stepl, num_init, _f);
	}
	if(_Pnts.size() < num_init) {
		std::cerr << "Do not have enough initial points." << std::endl;
		std::exit(-1);
	}

	Point<DIM> p;
	for(int i = 0; i != s; i++) {
		p = p + _stepl*(this -> get_beta_i(s - 1 - i))*_f(_Pnts[num_init - 1 - i]);
		p = p - (this -> get_alpha_i(s - 1 - i))*_Pnts[num_init - 1 - i];
	}
	p.set_time(_Pnts[num_init - 1].get_time() + _stepl);
	_Pnts.erase(_Pnts.begin());
	_Pnts.push_back(p);
};	

#else
//Do nothing.
#endif
